/*
 * Author: vyouzhi <vyouzhi@163.com>
 * http://www.xda.cn
 *
 * File: THREAD_LIB.H
 * Create Date: 2011-09-26 15:07:44
 *
 */
#ifndef THREAD_LIB_H_
#define THREAD_LIB_H_

#include <event.h>
#include <pthread.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>

#include "socket_lib.h"
#include "mem_lib.h"

#define ITEMS_PER_ALLOC 1024

typedef struct {
    pthread_t thread_id;        /* 线程ID */
    struct event_base *base;    /* 此线程的libevent句柄 */
    struct event notify_event;  /* 通知事件，主线程通过这个事件通知worker线程有新连接 */
    int notify_read_fd;      /* 通知事件关联的读fd，这和下面的notify_send_fd是一对管道，具体使用后面讲 */
    int notify_write_fd;         /* 通知事件关联的写fd，后面讲 */
	struct conn_queue *new_conn_queue; /* queue of new connections to handle */
} LIBEVENT_THREAD;

typedef struct {
    pthread_t thread_id;        /* 主线程ID */
    struct event_base *base;    /* libevent句柄 */
} LIBEVENT_DISPATCHER_THREAD;

typedef struct conn_queue_item CQ_ITEM;
struct conn_queue_item {
    int               sfd;
    CQ_ITEM          *next;
};

/* A connection queue. */
typedef struct conn_queue CQ;
struct conn_queue {
    CQ_ITEM *head;
    CQ_ITEM *tail;
    pthread_mutex_t lock;
    pthread_cond_t  cond;
};

typedef struct conn conn;
struct conn {
    int    sfd;
    struct event event;
    /*conn   *next;      Used for generating a list of conn structures 
    LIBEVENT_THREAD *thread;  Pointer to the thread object serving this connection */
};

conn *conns;
struct event_base *main_base;
pthread_mutex_t init_lock;
pthread_cond_t init_cond;
/*LIBEVENT_DISPATCHER_THREAD dispatcher_thread;*/
LIBEVENT_THREAD *threads;
pthread_t free_threads;
pthread_mutex_t free_threads_lock;

CQ_ITEM *cqi_freelist;
pthread_mutex_t cqi_freelist_lock;


void thread_libevent_process(int fd, short ev, void *arg);
void setup_thread(LIBEVENT_THREAD *me) ;
void *worker_libevent(void *arg) ;
void create_worker(void *(*func)(void *), void *arg);
void thread_init(int nthreads); 
void cq_init(CQ *cq) ;
CQ_ITEM *cq_pop(CQ *cq);
void cq_push(CQ *cq, CQ_ITEM *item) ;
CQ_ITEM *cqi_new(void) ;
void cqi_free(CQ_ITEM *item) ;
#endif /* THREAD_LIB_H_ */
/* vim: set ts=4 sw=4: */

